package cn.hnu.qq.client.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

import cn.hnu.qq.client.thread.ClientClientListener;
import cn.hnu.qq.entity.User;
import cn.hnu.qq.entity.message.ChartMessage;
import cn.hnu.qq.frame.ClientFrame;
import cn.hnu.qq.frame.CrowdChartDialog;
import cn.hnu.qq.frame.SingleChartDialog;
import cn.hnu.qq.global.MessageType;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * 中心控制器
 * 
 * @author jared
 * 
 */
public class CenterController {
	private static User curUser;

	private static Socket socket; // 连接服务器的socket TCP

	private static DatagramSocket dSocket;// UDP 聊天所用

	private static ObjectOutputStream output = null;

	private static ObjectInputStream input = null;

	private static MessageType[] waitObj = new MessageType[] {
			MessageType.LOGON, MessageType.LOGON_SUCCESS,
			MessageType.ACCOUNT_NOT_FOUND, MessageType.CHART,
			MessageType.IP_INFO, MessageType.PASSWORD_FALSE,
			MessageType.QUERY_IP_INFO, MessageType.USER_NOT_ONLINE ,
			MessageType.CROWD_INFO,MessageType.QUERY_CROWD_INFO}; // 线程同步锁

	private static Boolean isMessageArrived = false;

	private static ClientFrame client;

	private static SingleChartDialog singDialog;

	private static CrowdChartDialog crowdDialog;

	protected static Properties clientProperties;

	private static Map<Object, Object> session = new HashMap<Object, Object>();

	protected static Logger log;

	public Logger getLog() {
		return log;
	}

	public void setLog(Logger log) {
		this.log = log;
	}

	public void put(Object key, Object value) {
		session.put(key, value);
	}

	public Object get(Object key) {
		return session.get(key);
	}

	public void remove(Object key) {
		session.remove(key);
	}

	public SingleChartDialog getSingDialog() {
		return singDialog;
	}

	public static void setSingDialog(SingleChartDialog singDialog) {
		CenterController.singDialog = singDialog;
	}

	public CrowdChartDialog getCrowdDialog() {
		return crowdDialog;
	}

	public static void setCrowdDialog(CrowdChartDialog crowdDialog) {
		CenterController.crowdDialog = crowdDialog;
	}

	public DatagramSocket getdSocket() {
		return dSocket;
	}

	public static void setdSocket(DatagramSocket dSocket) {
		CenterController.dSocket = dSocket;
	}

	/**
	 * 控制器初始化连接服务器参数 ,客户端监听线程
	 */
	static {
		try {

			DOMConfigurator
					.configure(ClassLoader
							.getSystemResource("cn/hnu/qq/client/config/client.log4j.xml"));
			log = Logger.getLogger(CenterController.class);
			clientProperties = new Properties();
			clientProperties
					.load(ClassLoader
							.getSystemResourceAsStream("cn/hnu/qq/client/config/config.properties"));

			socket = new Socket(
					InetAddress.getByName(clientProperties
							.getProperty("server.ip")),
					Integer.valueOf(clientProperties.getProperty("server.port")));// 服务器参数

			dSocket = new DatagramSocket(Integer.valueOf(clientProperties
					.getProperty("client.port")));// 客户端监听的端口

			log.debug("启动udp监听线程");
			new ClientClientListener().start();// 启动udp监听线程
			log.debug("成功启动udp监听线程");
			log.debug("进入 CenterController 初始化完毕");
		} catch (Exception e) {
			System.err.println("服务器参数初始化失败");
			e.printStackTrace();
			System.exit(-1);
		}
	}

	public User getCurUser() {
		return curUser;
	}

	public void setCurUser(User curUser) {
		CenterController.curUser = curUser;
	}

	protected static synchronized ObjectOutputStream getOutput() {
		System.out.println("CenterController获取output");
		try {
			if (output == null) {
				output = new ObjectOutputStream(new BufferedOutputStream(
						socket.getOutputStream()));
			}
		} catch (IOException e) {
			System.err.println("初始化ObjectOutputStream失败");
			e.printStackTrace();
		}

		return output;
	}

	protected static synchronized ObjectInputStream getInput() {
		System.out.println("CenterController获取input");
		try {
			if (input == null) {
				input = new ObjectInputStream(new BufferedInputStream(
						socket.getInputStream()));
			}
		} catch (Exception e) {
			System.err.println("初始化ObjectInputStream失败");
			e.printStackTrace();
		}
		return input;
	}

	public void waitingMessageArriving() {
		synchronized (waitObj) {
			try {
				if (!isMessageArrived) {
					System.err.println("进入等待消息中。。。。。");
					waitObj.wait();
					isMessageArrived = false;
				}
			} catch (InterruptedException e) {
				System.err.println("等待超时！！");
				e.printStackTrace();
			}
		}

	}

	public void messageArrived(MessageType message) {
		log.debug("消息到达："+message);
		for (MessageType waitType : waitObj) {
			if (waitType.equals(message)) {
				synchronized (waitType) {
					isMessageArrived = true;
					System.err.println("消息抵达。。。。。");
					waitType.notifyAll();
				}
			}
		}
	}

	protected byte[] ObjectToArray(Object obj) {
		return JSON.toJSONBytes(obj, SerializerFeature.WriteClassName);
		// return
		// JSON.toJSONString(obj,SerializerFeature.WriteClassName).getBytes();
	}

	@SuppressWarnings("unchecked")
	protected Object ArrayToObject(byte[] obj, int length) {
		try {
			log.debug("从byte转化为对象");
			log.debug("转换JSON对象，JSON字符串:" + new String(obj, 0, length));

			return JSON.parse(new String(obj, 0, length));
		} catch (Exception e) {
			log.error("byte转化对象失败");
			e.printStackTrace();
		}
		return null;
	}

	public ClientFrame getClient() {
		return client;
	}

	public static void setClient(ClientFrame client) {
		CenterController.client = client;
	}

	protected void waitingMessageArriving(MessageType type) {
		log.debug("等待消息 ："+type);
		for (MessageType waitType : waitObj) {
			if (waitType.equals(type)) {
				synchronized (waitType) {
					try {
						if (!isMessageArrived) {
							waitType.wait();
							isMessageArrived = false;
						}
					} catch (Exception e) {
						e.printStackTrace();
					}

				}
			}
		}

	}
}
